#include <iostream>
#include "lib_json/json.h"
#include "tool/Utility.h"
#include "tool/Proto.h"
#include "worker/Worker.h"
#include "worker/ImgWriter.h"
#include "mgr/MsgSender.h"
#include "mgr/LogMgr.h"
#include "mgr/ImgWriterMgr.h"

Worker::Worker(int id, int interval, std::string url) {
	this->m_id = id;
	this->m_interval = interval;
	this->m_url = url;
}

Worker::~Worker() {
	
}

int Worker::InitVideo() {
	LOG_INFO("Worker No." << this->m_id << " Capture Video Start at CPU :" << this->m_url)
	// FFMPEG版本 
	// GStreamer 无法正常 使用 我吐了
	m_video_capture.open(this->m_url);

	if (!m_video_capture.isOpened()) {
		LOG_ERROR( "Worker No." << this->m_id << " Capture Video :" << this->m_url << " Failed!!!")
		return 1;
	}
	// 设置缓冲区没有buffer () 可能么得卵用
	m_video_capture.set(cv::CAP_PROP_BUFFERSIZE, 0);
	// TODO 都不知道起不起作用 设置都么得卵用
	this->m_fps = m_video_capture.get(cv::CAP_PROP_FPS);
	this->m_fps = this->m_fps == 0 ? 20 : this->m_fps;
	this->m_fps_interval = 1000 / this->m_fps;
	return 0;
}

int Worker::InitVideo_GPU() {
	// TODO 看不到有正常判断的接口 我去
	LOG_INFO("Worker No." << this->m_id << " Capture Video Start at GPU :" << this->m_url)
	try {
		m_video_capture_gpu = cv::cudacodec::createVideoReader(this->m_url);
	}
	catch(const std::exception&){
		LOG_ERROR( "Worker No." << this->m_id << " Capture Video :" << this->m_url << " Failed!!!")
	}
	// TODO 这里拿不到信息了 因为GPU去解码了 尴尬
	// 33 也有点问题 我吐了
	this->m_fps = 25;
	this->m_fps_interval = 40;
	return 0;
}

// 第三种 直接调用ffmpeg的版本
// TODO 暂时 只有软解
int Worker::InitVideo_FFMpegCPU() {
	// LOG_INFO("Worker No." << this->m_id << " Capture Video Start at FFMpeg :" << this->m_url)
	try {
		//新增
		// m_ifmt_ctx = avformat_alloc_context();
		//m_pkt = (AVPacket *)av_malloc(sizeof(AVPacket));
		m_ifmt_ctx = nullptr;
		//Register
		av_register_all();
		//Log TODO 这里强行这样好像不太好的样子
		av_log_set_level(AV_LOG_ERROR);
		//Network
		avformat_network_init();
		//Input
    	av_dict_set(&m_options, "rtsp_transport", "tcp", 0);
    	av_dict_set(&m_options, "stimeout", "2000000", 0);
    	av_dict_set(&m_options, "max_delay", "500000", 0);
		av_dict_set(&m_options, "buffer_size", "1024000", 0);
		int ret = 0;
		if ((ret = avformat_open_input(&m_ifmt_ctx, this->m_url.c_str(), 0, &m_options)) < 0) {
			LOG_ERROR("Worker No." << this->m_id << " Could not open input file :" << this->m_url)
			return -1;
		}
		if ((ret = avformat_find_stream_info(m_ifmt_ctx, 0)) < 0) {
			LOG_ERROR("Worker No." << this->m_id << " Failed to retrieve input stream information :" << this->m_url)
			return -1;
		}

		m_videoindex = -1;
		for (unsigned int i = 0; i < m_ifmt_ctx->nb_streams; i++) {
			if (m_ifmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {				
				m_videoindex = i;
				break;
			}
		}
		if(m_videoindex == -1){
			LOG_ERROR("Worker No." << this->m_id << " Failed to retrieve input stream information any video :" << this->m_url)
			return -1;
		}
	 	
		//Find H.264 Decoder
		m_pCodec = avcodec_find_decoder(m_ifmt_ctx->streams[m_videoindex]->codecpar->codec_id);
		if (m_pCodec == NULL) {
			LOG_ERROR("Worker No." << this->m_id << " Couldn't find Codec." << this->m_url)
			return -1;
		}
		m_pCodecCtx = avcodec_alloc_context3(m_pCodec);
		if (!m_pCodecCtx) {
			LOG_ERROR("Worker No." << this->m_id << " Could not allocate video codec context" << this->m_url)
			return -1;
		}
		// // TODO 这个值 估计要考虑考虑 先设置成2 试试看
		// m_pCodecCtx->thread_count = 2;
		// m_pCodecCtx->thread_safe_callbacks = 1;
		m_pCodecCtx->skip_frame = AVDISCARD_NONKEY;
		if (avcodec_open2(m_pCodecCtx, m_pCodec, NULL) < 0) {
			LOG_ERROR("Worker No." << this->m_id << " Couldn't open codec." << this->m_url)
			printf("Couldn't open codec.\n");
			return -1;
		}
		m_pframe = av_frame_alloc();
		if (!m_pframe) {
			LOG_ERROR("Worker No." << this->m_id << " Could not allocate video frame " << this->m_url)
			return -1;
		}
	}
	catch(const std::exception&){
		LOG_ERROR("Worker No." << this->m_id << " Capture Video :" << this->m_url << " Failed!!!")
		// TODO 可能需要通知外部消息 才行
	}
	return 0;
}

void Worker::ReadFrame() {
	// ========  多线程CPU版本==================================================================
	// TODO 这里结束 最好是通知下啥地方 自己炸了最好 暂时就先不管了
	if (InitVideo()) {
		this->m_status = 2;
		return;
	}
	// std::cout << "Worker No." << this->m_id << " Running On " << sched_getcpu() << std::endl;
	// 跟着帧数 + interval 走 抽帧逻辑 看看速度咋样
	int _frame_index =  0;
	while (!m_status)
	{
		try
		{
			// 猜测 不确定 这个吐帧 如果太快 会导致等帧 导致时间变慢 这太愚蠢了
			// std::chrono::time_point<std::chrono::system_clock> start_time = std::chrono::system_clock::now();
			// 试试看CPU版本用grab的方法 只有要真的吐帧再retreive
			if(!m_video_capture.grab()){
				LOG_WARN("Worker No." << this->m_id << " Video DisConnect!!!")
				InitVideo();
				continue;
			}
			_frame_index++;
			// 先1s 1帧
			if (_frame_index >= this->m_fps * this->m_interval / 1000.0f) // this->m_interval * 
			{
				// 帧数到了
				_frame_index = 0;
				m_index++;
				if (m_index > 10)
					m_index = 0;
				m_video_capture.retrieve(this->m_frame_cpu);
				ImgWriteInfo info;
				info.id = this->m_id;
				info.index = this->m_index;
				info.mat = this->m_frame_cpu.clone();
				ImgWriterMgr::instance().Push(info);
			}
		}
		catch (const std::exception& e)
		{
			LOG_ERROR("Worker No." << this->m_id << " " << e.what())
		}
	}
	this->m_frame_cpu.release();
	this->m_video_capture.release();
	this->m_status = 2;
	LOG_INFO("Worker No." << this->m_id << " Finish")

	
	// // // ========  原始CPU单线程版本==================================================================
	// if (InitVideo())return;
	// std::cout << "Worker No." << this->m_id << " On Your Service" << std::endl;
	// while (!m_status)
	// {
	// 	try
	// 	{
	// 		std::chrono::time_point<std::chrono::system_clock> start_time = std::chrono::system_clock::now();
	// 		m_video_capture >> this->m_frame;
	// 		if (this->m_frame.empty()) {
	// 			std::cout << "Worker No." << this->m_id << "Video DisConnect!!!" << std::endl;
	// 			InitVideo();
	// 			continue;
	// 		};
	// 		// std::chrono::time_point<std::chrono::system_clock> read_time = std::chrono::system_clock::now();
	// 		// std::cout << "Worker No." << this->m_id << " read time:" << std::chrono::duration_cast<std::chrono::milliseconds>(read_time - start_time).count() << std::endl;
	// 		SaveImg();
	// 		Send10010();
		
	// 		std::chrono::time_point<std::chrono::system_clock> end_time = std::chrono::system_clock::now();

	// 		std::chrono::milliseconds diff = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time);
	// 		if (diff.count() < this->m_interval) {
	// 			std::this_thread::sleep_for(std::chrono::milliseconds(this->m_interval) - diff);
	// 		}else{
	// 			std::cout << "Worker No." << this->m_id << " loop time warning:" << diff.count() << std::endl;
	// 			std::this_thread::sleep_for(std::chrono::milliseconds(this->m_interval));
	// 		}
	// 		if (m_index >= 10)
	// 			m_index = 0;
	// 		m_index++;
	// 	}
	// 	catch (const std::exception& e)
	// 	{
	//  	std::cout << e.what() << std::endl;
	// 	}
	// }
	// std::cout << "Worker No." << this->m_id << " Finish" << std::endl;
	
	// // ========  GPU单线程版本==================================================================
	// if (InitVideo_GPU())return;
	// std::cout << "Worker No." << this->m_id << " On Your Service" << std::endl;
	// while (!m_status)
	// {
	// 	try
	// 	{
	// 		std::chrono::time_point<std::chrono::system_clock> start_time = std::chrono::system_clock::now();
	// 		if(!m_video_capture_gpu->nextFrame(m_frame_gpu)){
	// 			std::cout << "Worker No." << this->m_id << "Video DisConnect!!!" << std::endl;
	// 			InitVideo_GPU();
	// 			continue;
	// 		}
	// 		m_frame_gpu.download(this->m_frame);
	// 		std::chrono::time_point<std::chrono::system_clock> read_time = std::chrono::system_clock::now();
	// 		std::cout << "Worker No." << this->m_id << " read time:" << std::chrono::duration_cast<std::chrono::milliseconds>(read_time - start_time).count() << std::endl;
	// 		SaveImg();
	// 		Send10010();
		
	// 		std::chrono::time_point<std::chrono::system_clock> end_time = std::chrono::system_clock::now();

	// 		std::chrono::milliseconds diff = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time);
	// 		if (diff.count() < this->m_interval) {
	// 			std::this_thread::sleep_for(std::chrono::milliseconds(this->m_interval) - diff);
	// 		}else{
	// 			std::cout << "Worker No." << this->m_id << " loop time warning:" << diff.count() << std::endl;
	// 			std::this_thread::sleep_for(std::chrono::milliseconds(this->m_interval));
	// 		}
	// 		if (m_index >= 10)
	// 			m_index = 0;
	// 		m_index++;
	// 	}
	// 	catch (const std::exception& e)
	// 	{
    //  	std::cout << e.what() << std::endl;
	// 	}
	// }
	// std::cout << "Worker No." << this->m_id << " Finish" << std::endl;

	//// ========  GPU多线程版本==================================================================
	// if (InitVideo_GPU())return;
	// std::this_thread::sleep_for(std::chrono::milliseconds(rand() % 100 + 1));
	// std::cout << "Worker No." << this->m_id << " On Your Service" << std::endl;
	// while (!m_status)
	// {
	// 	try
	// 	{
	// 		std::chrono::time_point<std::chrono::system_clock> start_time = std::chrono::system_clock::now();
	// 		if(!m_video_capture_gpu->nextFrame(m_frame_gpu)){
	// 			std::cout << "Worker No." << this->m_id << "Video DisConnect!!!" << std::endl;
	// 			InitVideo_GPU();
	// 			continue;
	// 		}
	// 		bool _btransfer = false;
	// 		if(!this->m_lock){			
	// 			m_frame_gpu.download(this->m_frame);
	// 			_btransfer = true;
	// 			this->m_lock = true;
	// 		}
	// 		std::chrono::time_point<std::chrono::system_clock> read_time = std::chrono::system_clock::now();
	// 		std::chrono::milliseconds diff_read = std::chrono::duration_cast<std::chrono::milliseconds>(read_time - start_time);
	// 		// std::cout << "Worker No." << this->m_id << " read time:" << diff_read.count() << std::endl;
			
	// 		if (diff_read.count() < this->m_fps_interval) {
	// 			std::this_thread::sleep_for(std::chrono::milliseconds(this->m_fps_interval) - diff_read);
	// 		}else{
	// 			// 超时直接睡1帧
	// 			std::cout << "Worker No." << this->m_id <<" read time warning:" << diff_read.count() <<" , _btransfer:" << _btransfer << std::endl;
	// 			std::this_thread::sleep_for(std::chrono::milliseconds(this->m_fps_interval));
	// 		}
	// 	}
	// 	catch (const std::exception& e)
	// 	{
    //		std::cout << e.what() << std::endl;
	// 	}
	// }
	//std::cout << "Worker No." << this->m_id << " Finish" << std::endl;
}

void Worker::GetFrameImage_OpencvGPU(){
	// cv::cuda::setDevice(1);
	LOG_INFO("Worker No." << this->m_id << " Capture Video Start at GPU :" << this->m_url)
	try {
		m_video_capture_gpu = cv::cudacodec::createVideoReader(this->m_url);
	}
	catch(const std::exception&){
		LOG_ERROR( "Worker No." << this->m_id << " Capture Video :" << this->m_url << " Failed!!!")
		m_status = 2;
		return;
	}

	try
	{
		std::chrono::time_point<std::chrono::system_clock> start_time = std::chrono::system_clock::now();
		if(!m_video_capture_gpu->nextFrame(m_frame_gpu)){
			std::cout << "Worker No." << this->m_id << "Video DisConnect!!!" << std::endl;
			m_status = 2;
			return;
		}
		m_frame_gpu.download(this->m_frame);
		std::chrono::time_point<std::chrono::system_clock> read_time = std::chrono::system_clock::now();
		std::cout << "Worker No." << this->m_id << " read time:" << std::chrono::duration_cast<std::chrono::milliseconds>(read_time - start_time).count() << std::endl;
		
		if (m_index >= 10)
			m_index = 0;
		m_index++;
		
		ImgWriteInfo info;
		info.id = this->m_id;
		info.index = this->m_index;
		info.mat = this->m_frame_cpu.clone();
		ImgWriterMgr::instance().Push(info);
		
		m_status = 2;
		return;
	}
	catch (const std::exception& e)
	{
		std::cout << e.what() << std::endl;
	}
}

void Worker::ReadFrame_FFMpegCPU() {
	// ========  FFMpeg CPU版本==================================================================
	if (InitVideo_FFMpegCPU()) return;
	LOG_INFO("Worker No." << this->m_id << " Start" )
	// std::cout << "Worker No." << this->m_id << " Running On " << sched_getcpu() << std::endl;
	int ret = 0;
	int count = 0;
	int maxRetryCount = 3;  //最大重试次数
    int retryCount = 0; //当前重试次数
	
    while(!m_status)
    {	
		try
		{
			if(m_ifmt_ctx == NULL || av_read_frame(m_ifmt_ctx, &m_pkt) < 0){
				if (retryCount < maxRetryCount)
				{
					LOG_WARN("Worker No." << this->m_id << " Video ReConnect " << retryCount)
					// 不过如果不算的话 感觉 解码有点牛逼的 47路流 CPU占用也挺少的
					av_usleep(1000*1000);  //等待1秒钟 进行重连 虽然这个操作很迷
					retryCount++;
					// TODO 姑且先调用一下这个暂时 如果不行 再说了
					avformat_close_input(&m_ifmt_ctx);
					if (avformat_open_input(&m_ifmt_ctx, this->m_url.c_str(), 0, &m_options) != 0)
					{
						LOG_ERROR("Worker No." << this->m_id << " Could not open input file :" << this->m_url)
						continue;
					}
					if (avformat_find_stream_info(m_ifmt_ctx, NULL) < 0)
					{
						LOG_ERROR("Worker No." << this->m_id << " Failed to retrieve input stream information. :" << this->m_url)
						continue;
					}
				}
				else
				{
					break;
				}
			}
			retryCount = 0;
			// 只处理 视频 帧
			// 看看能不能跳帧了 现在只处理了 I帧 那个skip_frame好像也有点问题的样子???
			if (m_pkt.stream_index == m_videoindex && (m_pkt.flags & AV_PKT_FLAG_KEY) && m_pkt.size > 0) {

				ret = avcodec_send_packet(m_pCodecCtx, &m_pkt);
				if (ret < 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
					// LOG_WARN("Worker No." << this->m_id << " avcodec_send_packet: ")
					av_packet_unref(&m_pkt);
					av_usleep(1000);
					continue;
				}
				ret = avcodec_receive_frame(m_pCodecCtx, m_pframe);
				if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
					// LOG_WARN("Worker No." << this->m_id << " avcodec_receive_frame: " << ret)
					av_packet_unref(&m_pkt);
					av_frame_unref(m_pframe);
					av_usleep(1000);
					continue;
				}
				
				// 
				// 这里就是解码成功了一帧 虽然不知道是个啥
				count++;
				if (m_index >= 10)
					m_index = 0;
				m_index++;
				// 这里就是解码成功了一帧 虽然不知道是个啥
				// 卧槽 解码成功还有不对的  我吐了
				// TODO 不知道这么判断行不行
				// 好像不行 应该是时序或者其他关系 导致有冲突了 直接在这里转换了只能
				std::chrono::time_point<std::chrono::system_clock> start_time = std::chrono::system_clock::now();
				int width = m_pframe->width;
				int height = m_pframe->height;
				if(m_frame_cpu.rows != height || m_frame_cpu.cols != width){
					m_frame_cpu = cv::Mat(height, width, CV_8UC3);
				}
				int cvLinesizes[1];
				cvLinesizes[0] = m_frame_cpu.step1();
				if(m_conversion == NULL){
					m_conversion = sws_getContext(width, height, (AVPixelFormat) m_pframe->format, width, height, AVPixelFormat::AV_PIX_FMT_BGR24, SWS_FAST_BILINEAR, NULL, NULL, NULL);
				}
				sws_scale(m_conversion, m_pframe->data, m_pframe->linesize, 0, height, &m_frame_cpu.data, cvLinesizes);
				
				ImgWriteInfo info;
				info.type = 1;
				info.id = this->m_id;
				info.index = this->m_index;
				info.mat = m_frame_cpu;
				ImgWriterMgr::instance().Push(info);

				std::chrono::time_point<std::chrono::system_clock> end_time = std::chrono::system_clock::now();
				std::chrono::milliseconds diff = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time);
				// LOG_INFO("ToCvMat Use Time: " << diff.count())
				av_usleep(1000);
			}
			// Free AvPacket
			av_packet_unref(&m_pkt);
			// av_free(pframe->data[0]);
			av_frame_unref(m_pframe); //后来才增加的 !! 每次重用之前应调用将frame复位到原始干净可用状态
			// https://www.cnblogs.com/leisure_chn/p/10404502.html
		}
		catch(const std::exception& e)
		{
			LOG_FATAL(e.what())
		}
    }
	if (m_conversion){
		sws_freeContext(m_conversion);
	}
	av_packet_unref(&m_pkt);
	if(m_pframe){
		av_frame_unref(m_pframe);
	}
	if(m_ifmt_ctx){
		avformat_close_input(&m_ifmt_ctx);
	}
	
	LOG_INFO("Worker No." << this->m_id << " Finish" )
	// TODO 这里大概还不能这么简单的操作 不然有的就不会重新连接了 我估计
	this->m_status = 2;
	// 估计有点内存泄漏的问题 TODO
	return;
}

void Worker::GetFrameImage_FFMpegCPU(){
	LOG_INFO("Worker No." << this->m_id << " Capture Video Start at FFMpeg :" << this->m_url)
	try {
		m_ifmt_ctx = nullptr;
		//Register
		av_register_all();
		//Log TODO 这里强行这样好像不太好的样子
		av_log_set_level(AV_LOG_ERROR);
		//Network
		avformat_network_init();
		//Input
    	av_dict_set(&m_options, "rtsp_transport", "tcp", 0);
    	av_dict_set(&m_options, "stimeout", "5000000", 0);
    	av_dict_set(&m_options, "max_delay", "500000", 0);
		av_dict_set(&m_options, "buffer_size", "1024000", 0);
		int ret = 0;
		if ((ret = avformat_open_input(&m_ifmt_ctx, this->m_url.c_str(), 0, &m_options)) < 0) {
			LOG_ERROR("Worker No." << this->m_id << " Could not open input file :" << this->m_url)
			throw std::exception();
		}
		if ((ret = avformat_find_stream_info(m_ifmt_ctx, 0)) < 0) {
			LOG_ERROR("Worker No." << this->m_id << " Failed to retrieve input stream information :" << this->m_url)
			throw std::exception();
		}

		m_videoindex = -1;
		for (unsigned int i = 0; i < m_ifmt_ctx->nb_streams; i++) {
			if (m_ifmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {				
				m_videoindex = i;
				break;
			}
		}
		if(m_videoindex == -1){
			LOG_ERROR("Worker No." << this->m_id << " Failed to retrieve input stream information any video :" << this->m_url)
			throw std::exception();
		}
	 	
		//Find H.264 Decoder
		m_pCodec = avcodec_find_decoder(m_ifmt_ctx->streams[m_videoindex]->codecpar->codec_id);
		if (m_pCodec == NULL) {
			LOG_ERROR("Worker No." << this->m_id << " Couldn't find Codec." << this->m_url)
			throw std::exception();
		}
		m_pCodecCtx = avcodec_alloc_context3(m_pCodec);
		if (!m_pCodecCtx) {
			LOG_ERROR("Worker No." << this->m_id << " Could not allocate video codec context" << this->m_url)
			throw std::exception();
		}
		// 测试机
		m_pCodecCtx->thread_count = 2;
		m_pCodecCtx->thread_safe_callbacks = 1;
		m_pCodecCtx->skip_frame = AVDISCARD_NONKEY;
		if (avcodec_open2(m_pCodecCtx, m_pCodec, NULL) < 0) {
			LOG_ERROR("Worker No." << this->m_id << " Couldn't open codec." << this->m_url)
			throw std::exception();
		}
		m_pframe = av_frame_alloc();
		if (!m_pframe) {
			LOG_ERROR("Worker No." << this->m_id << " Could not allocate video frame " << this->m_url)
			throw std::exception();
		}
	}
	catch(const std::exception&e){
		m_status = 2;
		return;
	}

	int ret = 0;
	while(1){
		if(av_read_frame(m_ifmt_ctx, &m_pkt) < 0){
			break;
		}
		if (m_pkt.stream_index == m_videoindex && m_pkt.size > 0) {

			ret = avcodec_send_packet(m_pCodecCtx, &m_pkt);
			if (ret < 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
				// LOG_WARN("Worker No." << this->m_id << " avcodec_send_packet: ")
				av_packet_unref(&m_pkt);
				av_usleep(1000);
				continue;
			}
			while(ret >= 0){
				ret = avcodec_receive_frame(m_pCodecCtx, m_pframe);
				if (ret == AVERROR(EAGAIN)){
					av_usleep(1000);
                    continue;
                }
                else if (ret < 0)
                {
					av_usleep(1000);
					continue;
                }
                break;
			}
			int width = m_pframe->width;
			int height = m_pframe->height;
			if (width == 0 || height == 0){
				continue;
			}
			if(m_frame_cpu.rows != height || m_frame_cpu.cols != width){
				m_frame_cpu = cv::Mat(height, width, CV_8UC3);
			}
			int cvLinesizes[1];
			cvLinesizes[0] = m_frame_cpu.step1();
			if(m_conversion == NULL){
				m_conversion = sws_getContext(width, height, (AVPixelFormat) m_pframe->format, width, height, AVPixelFormat::AV_PIX_FMT_BGR24, SWS_FAST_BILINEAR, NULL, NULL, NULL);
			}
			sws_scale(m_conversion, m_pframe->data, m_pframe->linesize, 0, height, &m_frame_cpu.data, cvLinesizes);
			
			ImgWriteInfo info;
			info.type = 1;
			info.id = this->m_id;
			info.index = this->m_index;
			info.mat = m_frame_cpu;
			ImgWriterMgr::instance().Push(info);
			// Free AvPacket
			av_packet_unref(&m_pkt);
			// av_free(pframe->data[0]);
			av_frame_unref(m_pframe); //后来才增加的 !! 每次重用之前应调用将frame复位到原始干净可用状态
			break;
		}	
	}
	// https://www.cnblogs.com/leisure_chn/p/10404502.html
	if (m_conversion){
		sws_freeContext(m_conversion);
	}
	avformat_close_input(&m_ifmt_ctx);
	LOG_INFO("Worker No." << this->m_id << " Finish" )
	this->m_status = 2;
	return;
}
// 预计有多少路 最多就这么多了
void Worker::Run() {
	m_thread = std::thread(&Worker::ReadFrame_FFMpegCPU, this);
	m_thread.detach();
// #ifdef LINUX
// 	cpu_set_t cpuset;
 
//     CPU_ZERO(&cpuset);
// 	// TODO  如果绑定CPU 还需要获取总CPU个数
//     CPU_SET(this->m_id % 40, &cpuset);
 
//     int rc =pthread_setaffinity_np(m_thread.native_handle(),sizeof(cpu_set_t), &cpuset);
 
//     if (rc != 0) {
//       std::cerr << "Error calling pthread_setaffinity_np: " << rc << "\n";
//     }
// #endif
}
void Worker::Run_OneFrame(int index){
	// m_thread = std::thread(&Worker::GetFrameImage_OpencvGPU, this);
	this->m_index = index;
	m_thread = std::thread(&Worker::GetFrameImage_FFMpegCPU, this);
	m_thread.detach();
	// #ifdef LINUX
	// 	cpu_set_t cpuset;
	
	// 	CPU_ZERO(&cpuset);
	// 	// TODO  如果绑定CPU 还需要获取总CPU个数
	// 	CPU_SET(this->m_id % 40, &cpuset);
	
	// 	int rc =pthread_setaffinity_np(m_thread.native_handle(),sizeof(cpu_set_t), &cpuset);
	
	// 	if (rc != 0) {
	// 	std::cerr << "Error calling pthread_setaffinity_np: " << rc << "\n";
	// 	}
	// #endif
}

void Worker::Stop() {
	this->m_status = 1;
}